﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Reflection;
using System.Text;

namespace Milan.Diagnostics
{
	/// <summary>
	/// Performs useful functions on a Pe file
	/// </summary>
	public class Pe
	{
		/// <summary>
		/// Retrieves the linker timestamp of the given file.
		/// </summary>
		/// <param name="filePath">A PE format file to get the linker time stamp of</param>
		/// <returns></returns>
		public static DateTime RetrieveLinkerTimestamp(string filePath)
		{
			DateTime returns = new DateTime();
			using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
			{
				fileStream.Position = 0x3C;
				var buffer = new Byte[8];
				fileStream.Read(buffer, 0, 4);
				fileStream.Position = BitConverter.ToUInt32(buffer, 0) + 8;
				fileStream.Read(buffer, 0, 4);
				UInt32 secondsSince1970 = BitConverter.ToUInt32(buffer, 0);
				returns = (new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(secondsSince1970);
				fileStream.Close();
			}
			return returns;
		}

		/// <summary>
		/// Retrieves the linker timestamp of the given assembly.
		/// </summary>
		/// <param name="assembly"></param>
		/// <returns>DateTime of the linker time stamp</returns>
		public static DateTime RetrieveLinkerTimestamp(System.Reflection.Assembly assembly)
		{
			return RetrieveLinkerTimestamp(assembly.Location);
		}

		/// <summary>
		/// Retrieves the linker timestamp of the entry assembly (.exe)
		/// </summary>
		/// <returns>DateTime of linker time stamp.</returns>
		public static DateTime RetrieveLinkerTimestamp()
		{
			return RetrieveLinkerTimestamp(Assembly.GetEntryAssembly());
		}

		/// <summary>
		/// Returns the linker timestamp as a unique and sortable string.
		/// </summary>
		/// <returns>sortable string yyMMddhhmmss</returns>
		public static string RetrieveLinkerTimestampAsString()
		{
			DateTime timestamp = RetrieveLinkerTimestamp();
			return timestamp.ToString("yyMMddhhmmss");
		}
	}
}
